#pragma once
#include "Node.h"
class UnorderedList
{
	class Iterator
	{
	public:
		typedef Iterator self_type;
		typedef Node value_type;
		typedef Node& reference;
		typedef Node* pointer;
		typedef forward_iterator_tag iterator_category;
		typedef int difference_type;
		
		Iterator(pointer ptr) : ptr_(ptr) { } //Constructor
		self_type operator++() { self_type i = *this; ptr_=ptr_->nextNode; return i; }
		self_type operator++(int junk) { ptr_=ptr_->nextNode; return *this; }
		reference operator*() { return *ptr_; }
		pointer operator->() { return ptr_; }
		bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
		bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
		
	private:
		pointer ptr_;
	};

public:
	Node *head;
	Node *tail;
	Node *freeHead;

	UnorderedList(void)
	{
		this->head = this->tail = this->freeHead = nullptr;
	}

	UnorderedList( int sizeOfFreeList )
	{
		this->head = this->tail = this->freeHead = nullptr;
		for( int i = 0; i < sizeOfFreeList; i++ )
		{
			if( freeHead == nullptr )
			{
				freeHead = new Node();
			}
			else
			{
				Node *n = new Node();
				n->nextNode = freeHead;
				freeHead = n;
			}
		}
	}

	~UnorderedList(void)
	{
		this->Clear();

		while( freeHead != nullptr )
		{
			if( freeHead->nextNode != nullptr )
			{
				Node *tempNode = nullptr;
				tempNode = freeHead->nextNode;
				delete freeHead;
				freeHead = tempNode;
			}
			else
			{
				delete freeHead;
				freeHead = nullptr;
			}
		}

	}

	void AddByInfo( string word, int freq )
	{
		if( freeHead != nullptr )
		{
			freeHead->word = word;
			freeHead->freq = freq;

			AddNode(freeHead);

			freeHead = freeHead->nextNode;

		}
		else
			AddNode( new Node( word, freq ) );

	}

	Node* NodeBefore( Node *actual )
	{
		Node *n = head;
		while( n != nullptr )
		{
			if( n->nextNode == actual )
				return n;
			n = n->nextNode;
		}
		return nullptr;
	}

	void AddNode( Node *n )
	{
		if( head == nullptr )	// empty list
		{
			head = tail = n;
		}
		else if ( head == tail )	// One node in list
		{
			head->nextNode = n;
			tail = n;
		}
		else
		{
			tail->nextNode = n;
			n->nextNode = nullptr;
			tail = n;
		}
	}

	void DeleteHeaderNode()	// Pop_front()
	{
		if( head != tail )
		{

			Node *temp = freeHead;
			freeHead = head;
			head = freeHead->nextNode;
			freeHead->nextNode = temp;
			
		}
		else
		{
			Node *temp = freeHead;
			freeHead = head;
			head = freeHead->nextNode;
			freeHead->nextNode = temp;


			head = tail = nullptr;
		}
	}

	void Clear()
	{
		while( head != nullptr )
			DeleteHeaderNode();
	}

	void Print()
	{
		Node *current = head;
		bool done = false;
		while( !done )
		{
			if( current != tail )
			{
				current->Print();
				current = current->nextNode;
			}
			else
			{
				current->Print();
				done = true;
			}
		}
		
	}

	bool WordInList( string word )
	{
		Node *current = head;

		if( head == nullptr )
			return false;

		while( true )
		{
			if( current->word == word )
			{
				current->freq++;
				return true;
			}
			

			if( current == tail )
			{
				if( current->word == word )
				{
					current->freq++;
					return true;
				}
				else
					return false;
			}
			current = current->nextNode;
		}
	}

	void ReadFromFile( string filename )
	{
		ifstream fin;
		string str, strRow;

		try
		{
			fin.open( filename );

			while( getline( fin, strRow ) )
			{
				istringstream iss( strRow );


				while( getline( iss, str, ' ' ) )
				{
					if( str[str.size() -1] == '.' || str[str.size() -1] == ',' )
						str[str.size() -1] = NULL;

					if( !WordInList( str ) ) // Word is NOT already in list
					{
						AddByInfo( str, 1 );
					}
				}
			}
		}
		catch( exception e )
		{
			cout << "Exception" << filename << endl;
			cout << e.what() << endl;
		}

		cout << "Done reading" << endl;

		fin.close();
	}

	void PrintMaximumFreq()
	{
		Node *current = head;
		int currentMax = 0;
		Node *temp = head;
		bool done = false;
		while( !done )
		{
			if( current != tail )
			{
				if( current->freq > currentMax )
				{
					currentMax = current->freq;
					temp = current;
				}

				current = current->nextNode;
			}
			else
			{
				if( current->freq > currentMax )
				{
					currentMax = current->freq;
					temp = current;
				}
				done = true;
			}
		}

		cout << "The word that occurs max number of times is: " << temp->word << ", and its used " << temp->freq << " times." << endl;
	}

	int NumberOfWords()
	{
		int numberOfWords = 0;

		for( auto it = begin(); it != end(); it++ )
		{
			numberOfWords += it->freq;
		}

		return numberOfWords;

	}

	Iterator begin()
	{
		return Iterator(head);
	}

	Iterator end()
	{
		return Iterator(nullptr);
	}

};

